// Copyright (c) 2022 Presto Labs Pte. Ltd.
// Author: lucasyoo

#include "coin2/strategy/hamm/hamm.h"
#include "coin2/base/config/args.h"

void AddCommonSimOptions(cxxopts::Options* opt) {
  using coin2::base::config::AddDriverOptions;
  using coin2::base::config::AddFeedArchiveOptions;
  using coin2::base::config::AddIntervalOptions;
  using coin2::base::config::AddProductOptions;

  opt->add_options()("config", "", cxxopts::value<std::string>());
  opt->add_options()("help", "");
  AddDriverOptions(opt);
  AddIntervalOptions(opt);
  AddProductOptions(opt);
  AddFeedArchiveOptions(opt);
}

void ParseSimOptions(const cxxopts::ParseResult& res, coin2::app::DriverConfig* config) {
  using coin2::base::config::GetEnclosingInterval;
  using coin2::base::config::ParseIntervalOptions;
  using coin2::base::config::ParseProductOptions;
  using coin2::base::config::ParseDriverOptions;

  ParseDriverOptions(res, config);
  ParseIntervalOptions(
      res,
      config->mutable_feed()->mutable_common()->mutable_archive()->mutable_interval());
  ParseProductOptions(res, config->mutable_feed());
  auto* mut_sim_config = config->mutable_order()->mutable_common()->mutable_sim_config();
  mut_sim_config->set_result_format(
      coin2::exchange::order::SimConfig::RESULT_FORMAT_PROTO_FILE_DUMP);
  auto begin_end = GetEnclosingInterval(*config);
  mut_sim_config->set_start_timestamp(begin_end.first);
  mut_sim_config->set_end_timestamp(begin_end.second);
}


int main(int argc, char* argv[]) {
  coin2::app::DriverConfig app;
  cxxopts::Options opt("hamm sim", "hamm sim");
  AddCommonSimOptions(&opt);

  auto res = opt.parse(argc, argv);
  if (res.count("help")) {
    std::cout << opt.help({"HAMM SIM HELP"}) << std::endl;
    return 0;
  }

  ParseSimOptions(res, &app);

  app.mutable_log()->set_log_file("");
  ::coin2::base::InitLogging(argv[0], app.log());

  int64_t start_time = app.order().common().sim_config().start_timestamp();
  coin2::strategy::hamm::HammStrategy strategy(res["config"].as<std::string>(), start_time);

  CHECK_GE(app.order().exchanges_size(), 1);
  for (auto& [name, config] : *(app.mutable_order()->mutable_exchanges())) {
    strategy.UpdateSimConfig(name, config.mutable_sim_config());
  }

  coin2::app::impl::Driver driver(app, &strategy);
  driver.Run();
  return 0;
}
